package com.xinzhitong.www.controller;

import com.xinzhitong.www.enumeration.RoleType;
import com.xinzhitong.www.exception.BusyException;
import com.xinzhitong.www.exception.certification.IncorrectCertificationException;
import com.xinzhitong.www.exception.checkcode.CheckCodeInvalidException;
import com.xinzhitong.www.exception.checkcode.WrongCheckCodeException;
import com.xinzhitong.www.exception.email.NotRegisteredEmailException;
import com.xinzhitong.www.exception.personalinfo.*;
import com.xinzhitong.www.exception.phone.ContainsOtherCharacterException;
import com.xinzhitong.www.exception.phone.MultiBoundPhoneException;
import com.xinzhitong.www.exception.phone.NotBoundPhoneException;
import com.xinzhitong.www.exception.phone.PhoneLengthNotStandardException;
import com.xinzhitong.www.exception.register.PasswordIsNotStandardException;
import com.xinzhitong.www.exception.register.UsernameExistException;
import com.xinzhitong.www.exception.register.UsernameIsNotStandardException;
import com.xinzhitong.www.pojo.TempAccount;
import com.xinzhitong.www.pojo.User;
import com.xinzhitong.www.service.UserService;
import com.xinzhitong.www.utils.EmailUtils;
import com.xinzhitong.www.utils.Message;
import com.xinzhitong.www.utils.SMSUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.annotation.RequiresGuest;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 账户控制器
 *
 * @author 徐鑫 魏骆淳
 */
@CrossOrigin
@RestController
@RequestMapping("user")
public class UserController {

    @Resource
    UserService userService;

    /**
     * 发送激活/验证邮件
     *
     * @param tempAccount 临时账号信息
     * @return 响应信息
     */
    @ResponseBody
    @RequestMapping(value = "email", method = RequestMethod.POST)
    public Message email(
            @RequestBody TempAccount tempAccount,
            @RequestParam("emailType") EmailUtils.EmailType emailType,
            @RequestParam("targetType") RoleType targetType
    ) {
        String msg = "邮件已发送至您的注册邮箱";
        try {
            userService.sendEmail(tempAccount, emailType, targetType);
            return Message.createSuc(msg);
        } catch (UsernameExistException e) {
            e.printStackTrace();
            msg = "该邮箱已被注册";
        } catch (PasswordIsNotStandardException e) {
            e.printStackTrace();
            msg = "密码格式不正确";
        } catch (NotRegisteredEmailException e) {
            e.printStackTrace();
            msg = "邮箱尚未注册";
        }
        return Message.createErr(msg);
    }

    /**
     * 激活邮箱账号
     *
     * @param randomKey 随机密钥
     * @return 显示信息
     */
    @ResponseBody
    @RequestMapping(value = "emailAccountActive", method = RequestMethod.GET)
    public String emailAccountActive(
            @RequestParam("randomKey") String randomKey
    ) {
        try {
            userService.activeEmailAccount(randomKey);
        } catch (NullPointerException e) {
            e.printStackTrace();
            return "invalid message";
        }
        return "register success";
    }

    /**
     * 邮箱账号重置密码
     *
     * @param randomKey 随机密钥
     * @return 响应信息
     */
    @ResponseBody
    @RequestMapping(value = "emailAccountPasswordReset", method = RequestMethod.GET)
    public String emailAccountPasswordReset(
            @RequestParam("randomKey") String randomKey
    ) {
        try {
            userService.resetEmailAccountPassword(randomKey);
        } catch (NullPointerException e) {
            e.printStackTrace();
            return "invalid message";
        }
        return "reset success";
    }

    /**
     * 获取昵称
     *
     * @return 昵称
     */
    @ResponseBody
    @RequestMapping(value = "getNickname", method = RequestMethod.GET)
    public Message getNickName() {
        return Message.createSuc(((User) SecurityUtils.getSubject().getPrincipal()).getNickname());
    }

    /**
     * 普通登录
     *
     * @param user 用户（用户名，密码）
     * @return 响应信息
     */
    @ResponseBody
    @RequestMapping(value = "login", method = RequestMethod.POST)
    public Message login(@RequestBody User user) {
        String msg = "登录成功";
        try {
            userService.login(user);
            return Message.createSuc(msg);
        } catch (DisabledAccountException e) {
            e.printStackTrace();
            msg = "账号已被禁用";
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            msg = "账号不存在";
        } catch (ExcessiveAttemptsException e) {
            e.printStackTrace();
            msg = "登录失败次数过多";
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            msg = "账号或密码输入错误";
        } catch (ExpiredCredentialsException e) {
            msg = "密码失效";
        }
        return Message.createErr(msg);
    }

    /**
     * 验证码登录（暂时废弃）
     *
     * @param phone     手机号码
     * @param checkCode 验证码
     * @return 响应信息
     */
    @ResponseBody
    @RequestMapping(value = "--loginByPhone--", method = RequestMethod.POST)
    public Message login(@RequestParam("phone") String phone, @RequestParam("checkCode") String checkCode) {
        String msg = "登录成功";
        try {
            userService.login(phone, checkCode);
            return Message.createSuc(msg);
        } catch (CheckCodeInvalidException e) {
            e.printStackTrace();
            msg = "请先获取校验码";
        } catch (WrongCheckCodeException e) {
            e.printStackTrace();
            msg = "校验码不正确";
        } catch (DisabledAccountException e) {
            e.printStackTrace();
            msg = "账号已被禁用";
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            msg = "账号不存在";
        } catch (ExcessiveAttemptsException e) {
            e.printStackTrace();
            msg = "登录失败次数过多";
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            msg = "用户名/密码错误";
        } catch (ExpiredCredentialsException e) {
            msg = "密码失效";
        }
        return Message.createSuc(msg);
    }

    /**
     * 普通注册
     *
     * @param user 用户（用户名，密码，已废弃）
     * @return 响应信息
     * @throws BusyException 系统繁忙
     */
    @ResponseBody
    @RequestMapping(value = "register", method = RequestMethod.POST)
    public Message register(@RequestBody User user) throws BusyException {
        try {
            userService.register(user);
            return Message.createSuc("注册成功，请前往登录界面登录");
        } catch (UsernameExistException e) {
            e.printStackTrace();
            return Message.createErr("用户名已存在");
        } catch (UsernameIsNotStandardException e) {
            e.printStackTrace();
            return Message.createErr("用户名由xxx组成");
        } catch (PasswordIsNotStandardException e) {
            e.printStackTrace();
            return Message.createErr("密码由xxx组成");
        }
    }

    /**
     * 手机号码注册
     *
     * @param tempAccount 临时账户信息
     *                    phone 电话号码
     *                    password 密码
     *                    checkCode 验证码
     * @return 响应信息
     */
    @RequiresGuest
    @ResponseBody
    @RequestMapping(value = "registerByPhone", method = RequestMethod.POST)
    public Message registerByPhone(
            @RequestBody TempAccount tempAccount
    ) {
        String msg = "注册成功";
        userService.register(tempAccount.getPhone(), tempAccount.getPassword(), tempAccount.getCheckCode());
        return Message.createSuc(msg);
    }

    /**
     * 重置密码
     *
     * @param tempAccount 临时账户信息
     *                    phone 电话号码
     *                    password 密码
     *                    checkCode 验证码
     * @return 响应信息
     */
    @RequestMapping(value = "resetPassword", method = RequestMethod.POST)
    @ResponseBody
    public Message resetPassword(
            @RequestBody TempAccount tempAccount
    ) {
        String msg = "密码已修改，请重新登录";
        userService.resetPassword(tempAccount.getPhone(), tempAccount.getPassword(), tempAccount.getCheckCode());
        return Message.createSuc(msg);
    }

    /**
     * 使用旧密码进行重置密码
     *
     * @param map 参数列表
     *            oldOne 旧密码
     *            newOne 新密码
     * @return 响应信息
     */
    @RequestMapping(value = "resetPasswordByOldOne", method = RequestMethod.POST)
    public Message resetPasswordByOldOne(
            @RequestBody Map<String, String> map
    ) {
        String msg = "密码已修改，请重新登录";
        try {
            userService.resetPasswordByOldOne(map.get("oldOne"), map.get("newOne"));
            return Message.createSuc(msg);
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            msg = "原密码错误";
        }
        return Message.createErr(msg);
    }

    /**
     * 向指定手机号码发送验证码
     *
     * @param phone       手机号码
     * @param smsCodeType 验证码类型
     * @return 响应信息
     */
    @RequestMapping(value = "SMSCode", method = RequestMethod.POST)
    public Message SMSCode(
            @RequestParam("phone") String phone,
            @RequestParam("smsCodeType") SMSUtil.SMSCodeType smsCodeType
    ) {
        String msg = "验证码发送成功";
        try {
            userService.sendSMS(phone, smsCodeType);
            return Message.createSuc(msg);
        } catch (NotBoundPhoneException e) {
            e.printStackTrace();
            msg = "该手机号未注册";
        } catch (MultiBoundPhoneException e) {
            e.printStackTrace();
            msg = "该手机号已注册";
        } catch (PhoneLengthNotStandardException e) {
            e.printStackTrace();
            msg = "请输入正确的手机号";
        } catch (ContainsOtherCharacterException e) {
            e.printStackTrace();
            msg = "手机号码处带有其他字符！";
        } catch (Exception e) {
            e.printStackTrace();
            msg = "验证码生成失败，请稍后再试";
        }
        return Message.createErr(msg);
    }

    /**
     * 退出
     *
     * @return 响应信息
     */
    @RequestMapping(value = "logout", method = RequestMethod.POST)
    public Message logout() {
        String msg = "退出成功";
        Subject subject = SecurityUtils.getSubject();
        try {
            //更新上次登录时间
            userService.recordUsersLastLoginTime();
            subject.logout();
            return Message.createSuc(msg);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            msg = "请先登录！";
        }
        return Message.createErr(msg);
    }

    /**
     * 获取用户报名信息
     *
     * @return 报名信息
     */
    @RequestMapping(value = "enrollInfo", method = RequestMethod.GET)
    public Message enrollInfo() {
        String msg;
        try {
            return Message.createSuc(userService.getEnrollInfo());
        } catch (RealNameIsNotExistException e) {
            e.printStackTrace();
            msg = "请先完善真实姓名";
        } catch (IdIsNotExistException e) {
            e.printStackTrace();
            msg = "请先完善身份证号码";
        } catch (ContactIsNotExistException e) {
            e.printStackTrace();
            msg = "请先完善联系方式";
        }
        return Message.createErr(msg);
    }

    /**
     * 获取用户主页信息
     *
     * @return 用户主页信息
     */
    @RequestMapping(value = "mainInfo", method = RequestMethod.GET)
    public Message mainInfo() {
        String msg;
        try {
            return Message.createSuc(userService.getMainInfo());
        } catch (PersonInfoInvalidException e) {
            e.printStackTrace();
            msg = "用户信息不存在";
        }
        return Message.createErr(msg);
    }

    /**
     * 修改信息
     *
     * @param head       头像
     * @param nickname   昵称
     * @param sex        性别
     * @param province   省
     * @param city       市
     * @param area       区
     * @param birthday   生日
     * @param occupation 职业
     * @return 响应信息
     */
    @RequestMapping(value = "userInfo", method = RequestMethod.POST)
    @ResponseBody
    public Message userInfo(
            @RequestParam(required = false) MultipartFile head,
            @RequestParam(required = false) String nickname,
            @RequestParam(required = false) Boolean sex,
            @RequestParam(required = false) String province,
            @RequestParam(required = false) String city,
            @RequestParam(required = false) String area,
            @RequestParam(required = false) String birthday,
            @RequestParam(required = false) String occupation
    ) {
        //新建新信息
        User newInfo =
                new User(null,
                        null,
                        sex,
                        null,
                        nickname,
                        province,
                        city,
                        area,
                        birthday,
                        occupation,
                        null,
                        null,
                        null,
                        null,
                        null
                );
        String msg;
        try {
            userService.editUserInfo(head, newInfo);
            return Message.createSuc("修改成功");
        } catch (MultipleSexSettingException e) {
            e.printStackTrace();
            msg = "请勿重复设置性别";
        } catch (IOException e) {
            e.printStackTrace();
            msg = "头像读取错误，请重新上传";
        }
        return Message.createErr(msg);
    }

    /**
     * 修改信息
     *
     * @param head       头像
     * @param nickname   昵称
     * @param sex        性别
     * @param province   省
     * @param city       市
     * @param area       区
     * @param birthday   生日
     * @param occupation 职业
     * @return 响应信息
     * test
     */
    @RequestMapping(value = "userInfoTest", method = RequestMethod.POST)
    @ResponseBody
    public Message userInfoTest(
            @RequestParam(required = false) Integer head,
            @RequestParam(required = false) String nickname,
            @RequestParam(required = false) Boolean sex,
            @RequestParam(required = false) String province,
            @RequestParam(required = false) String city,
            @RequestParam(required = false) String area,
            @RequestParam(required = false) String birthday,
            @RequestParam(required = false) String occupation
    ) {
        //新建新信息
        User newInfo =
                new User(null,
                        null,
                        sex,
                        null,
                        nickname,
                        province,
                        city,
                        area,
                        birthday,
                        occupation,
                        null,
                        null,
                        null,
                        null,
                        null
                );
        String msg = null;
        try {
            HashMap<String, Object> re = userService.editUserInfoTest(head, newInfo);
            return Message.createSuc(re);
        } catch (MultipleSexSettingException e) {
            e.printStackTrace();
            msg = "请勿重复设置性别";
        } catch (IOException e) {
            e.printStackTrace();
            msg = "头像读取错误，请重新上传";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Message.createErr(msg);
    }

    /**
     * 获取用户主页信息
     *
     * @return 用户主页信息
     */
    @RequestMapping(value = "mainInfoNew", method = RequestMethod.GET)
    public Message mainInfoNew() {
        String msg;
        try {
            return Message.createSuc(userService.getMainInfoNew());
        } catch (PersonInfoInvalidException e) {
            e.printStackTrace();
            msg = "用户信息不存在";
        }
        return Message.createErr(msg);
    }

    /**
     * 修改信息
     *
     * @param headNum    头像
     * @param nickname   昵称
     * @param sex        性别
     * @param province   省
     * @param city       市
     * @param area       区
     * @param birthday   生日
     * @param occupation 职业
     * @return 响应信息
     */
    @RequestMapping(value = "userInfoNew", method = RequestMethod.POST)
    @ResponseBody
    public Message userInfoNew(
            @RequestParam(required = false) Integer headNum,
            @RequestParam(required = false) String nickname,
            @RequestParam(required = false) Boolean sex,
            @RequestParam(required = false) String province,
            @RequestParam(required = false) String city,
            @RequestParam(required = false) String area,
            @RequestParam(required = false) String birthday,
            @RequestParam(required = false) String occupation
    ) {
        //新建新信息
        User newInfo =
                new User(null,
                        null,
                        sex,
                        null,
                        nickname,
                        province,
                        city,
                        area,
                        birthday,
                        occupation,
                        null,
                        null,
                        null,
                        null,
                        null
                );
        String msg;
        try {
            userService.editUserInfo(headNum, newInfo);
            return Message.createSuc("修改成功");
        } catch (MultipleSexSettingException e) {
            e.printStackTrace();
            msg = "请勿重复设置性别";
        } catch (IOException e) {
            e.printStackTrace();
            msg = "头像读取错误，请重新上传";
        }
        return Message.createErr(msg);
    }

    /**
     * 实名认证
     *
     * @param front    身份证正面照
     * @param behind   身份证背面照
     * @param realname 真实姓名
     * @param id       身份证号
     * @return 响应信息
     */
    @RequestMapping(value = "certification", method = RequestMethod.POST)
    public Message certification(
            @RequestParam("front") MultipartFile front,
            @RequestParam("behind") MultipartFile behind,
            @RequestParam("realname") String realname,
            @RequestParam("id") String id
    ) {
        String msg = "认证成功";
        try {
            userService.recordCertification(front, behind, realname, id);
            return Message.createSuc(msg);
        } catch (IncorrectCertificationException e) {
            e.printStackTrace();
            msg = "认证失败，请确认身份证件信息与本人信息一致";
        }
        return Message.createErr(msg);
    }

    /**
     * 判断用户是否认证
     *
     * @return TRUE或者FALSE
     */
    @RequestMapping(value = "userAuthentication", method = RequestMethod.GET)
    public Message ifUserAuthentication() {
        return Message.createSuc(userService.ifUserAuthentication());
    }

    /**
     * 尝试直接登陆
     *
     * @return 是否成功登陆
     */
    @RequestMapping(value = "loginTry", method = RequestMethod.POST)
    public Message loginTry() {
        Subject subject = SecurityUtils.getSubject();
        if (subject.getPrincipal() == null)
            return Message.createSuc(false);
        return Message.createSuc(true);
    }

}
